package main

import (
	"fmt"
	"unsafe"
)

func main() {

	t := T{}
	calStructCap(t)
	fmt.Println(unsafe.Sizeof(t))
	fmt.Println("字段相当于变量t其实位置的偏移量：", unsafe.Offsetof(t.c))
	fmt.Println("一等公民的对齐系数：", unsafe.Alignof(calStructCap))
	println(calStructCap)
}

/*
从大白的文章总我们可以知道，
1. 结构体的内存结构是一种简单的平铺结构
2. 结构体在参数读取的时候会自动你padiing--自动将对象字段尽量弄到完整的情况
*/

/* 复习一下关于结构体的初始化
1. 首先就是根据字段的大小排列，然后彼此之间进行padding，直到所有的内存都对齐了
2. 接下来就是对齐整个结构体(圆整到8的倍数上去)，因为你单个对齐的话，后面变成数组就又不对齐了
*/
// 比如有下面结构体
type T struct {
	a byte
	b int64
	c uint16
}

// 注意了，转换接口的话，会变化大小的？--是不是接口换掉了内存对齐？
func calStructCap(t interface{}) {
	fmt.Println("占用内存的大小：", unsafe.Sizeof(t))     // 接口表示输出的就是16个字节
	fmt.Println("占用内存的大小：", unsafe.Sizeof(t.(T))) // 具体类型输出的还是24个字节
	fmt.Println("字段相当于变量t其实位置的偏移量：", unsafe.Offsetof(t.(T).c))
}

// 程序严格要求主动填充的时候
// type mstats struct {
// 	// ... ... ]
// 	// Add an uint32 for even number of size classes to align below fields
// 	// to 64 bits for atomic operations on 32 bit platforms.
// 	_ [1 - _NumSizeClasses%2]uint32 // 这里做了主动填充
// 	last_gc_nanotime uint64 // last gc (monotonic time)
// 	last_heap_inuse uint64 // heap_inuse at mark termination of the previous GC
// 	// ... ...
// }
